#include "utilfun.h"
#include <string>
#include <stdio.h>
#include <stdlib.h>
//#include "const.h"
#include <Windows.h>
#include <assert.h>
#define  MAXSTRLEN 1024

bool split_string(char *str, const char *cut, vector<char *> &strs){
	size_t size = 0;
	char *p=str,*q;
	bool ret=false;
	if(!str) return ret;
	strs.clear();
	while (q=strstr(p,cut)){
		*q=0;
		strs.push_back(p);
		p=q+strlen(cut);
		ret=true;
	}
	strs.push_back(p);
	return ret;
}


bool build_table(ifstream &fin, vector<vector<string> >& table,int &lines)
{
	char line[MAXSTRLEN];
	char fmt[512];
	table.clear();
	int i;
	bool not_end=true;
	while(not_end=(!fin.eof())){
		fin.getline(line,MAXSTRLEN-1);
		lines++;
		if(line[0]){
			
			vector<char *>columns;
			split_string(line,"\t",columns);
			vector<string> row(5);
			row[0]=columns[0];
			row[1]=columns[0];	
			row[2]=columns[1];
			row[3]=columns[2];
			row[4]=columns[3];
				
			table.push_back(row);
		}else{
			//return not_end;
			goto RETURN_TAG;
		}
	}

RETURN_TAG:
	for (int i=0;i<table.size();i++)
	{
		vector<string>& row = table[i];
		int par = atoi(row[3].c_str());
		if (par==-1)
			par = table.size();
		sprintf_s(fmt,512,"%d",par);
		row[3]=fmt;
	}

	return not_end;
}






int vector_cmp(const vector<int> & s, const vector<int> & t) 
//-1 : s<t 1:s>t 0:s==t
{
	int size=s.size()>t.size()?t.size():s.size();
	int i;
	for(i=0;i<size;i++){
		int j1=s.size()-1-i;
		int j2=t.size()-1-i;
		if(s[j1]>t[j2])
			return 1;
		else if(s[j1]<t[j2])
			return -1;
	}
	if(s.size()<t.size())
		return -1;
	else if(s.size()>t.size())
		return 1;
	else
		return 0;
}

int WriteMap(std::string fname, std::map<std::string, int> *m) {
	int count = 0;
	if (m->empty())
		return 0;

	FILE *fp = fopen(fname.c_str(), "w");
	if (!fp)
		return -errno;

	for(std::map<std::string, int>::iterator it = m->begin(); it != m->end(); it++) {
		fprintf(fp, "%s=%d\n", it->first.c_str(), it->second);
		count++;
	}

	fclose(fp);
	return count;
}

int ReadMap(std::string fname, std::map<std::string, int> *m) 
{
	int count = 0;

	FILE *fp = fopen(fname.c_str(), "r");
	if (!fp)
		return -errno;

	m->clear();

	char buf[1024];
	size_t buflen = 0;

	while(fgets (buf, 1024, fp) > 0) {
		char *nl = strchr(buf, '\n');
		if (nl == NULL)
			continue;
		*nl = 0;

		char *sep = strchr(buf, '=');
		if (sep == NULL)
			continue;
		*sep = 0;
		sep++;

		std::string s1 = buf;
		std::string s2 = sep;

		(*m)[s1] = atoi(s2.c_str());

		count++;
	}

	fclose(fp);
	return count;
}

int WriteVecStr(std::string fname,std::vector<std::string>& vec)
{
	FILE *fp = fopen(fname.c_str(), "w");
	if (!fp)
		return -errno;

	for (int i=0;i<vec.size();i++)
	{
		fprintf(fp, "%s\n",vec[i].c_str());
	}
	fclose(fp);
	return vec.size();
}

int ReadVecStr(std::string fname,std::vector<std::string>& vec)
{

	FILE *fp = fopen(fname.c_str(), "r");
	if (!fp)
		return -errno;

	vec.clear();

	char buf[1024];
	size_t buflen = 0;

	while(fgets (buf, 1024, fp) > 0) {
		char *nl = strchr(buf, '\n');
		if (nl == NULL)
			continue;
		*nl = 0;
		if(strlen(buf)>0)
			vec.push_back(buf);

	}

	fclose(fp);

	return vec.size();
}


void SaveBinDouble(const char* file,int num,double* data)
{
	FILE *fp = fopen(file, "wb");
	if (!fp) {
		printf("warning:%s can't open!\n",file);
		return ;
	}
	fwrite(&num,sizeof(int),1,fp);
	fwrite(data,sizeof(double),num,fp);
	fclose(fp);
	return ;
}

void ReadBinDouble(const char* file,int num,double* data)
{
	FILE *fp = fopen(file, "rb");
	if (!fp) {
		//printf("warning:%s can't open!\n",file);
		char buf[512];
		sprintf(buf,"ERROR:%s can't open!\n",file);
		printf(buf);
		::MessageBoxA(0,buf,"ERROR",MB_OK | MB_ICONEXCLAMATION);
		return ;
	}
	int fd_num;
	fread(&fd_num,sizeof(int),1,fp);
	assert(fd_num==num);
	int num_rd = fread(data,sizeof(double),fd_num,fp);
	assert(num_rd==num);
	fclose(fp);
	return ;
}

void SaveTxtDouble(const char* file,int num,double* data)
{
	FILE *fp = fopen(file, "w");
	if (!fp) return ;
	for (int i=0;i<num;i++)
		fprintf(fp, "%lf\n",data[i]);
	fclose(fp);

}

void ReadTxtDouble(const char* file,int num,double* data)
{
	FILE *fp = fopen(file, "r");
	if (!fp) return ;
	char buf[1024];
	int icount=0;
	while(fgets (buf, 1024, fp) > 0) {
		char *nl = strchr(buf, '\n');
		if (nl == NULL)
			continue;
		*nl = 0;
		if(strlen(buf)>0)
		{
			data[icount]=atof(buf);
			icount++;
		}
	}
	fclose(fp);
	assert(num==icount);
}

void  _assert_loc (const char *expr, const char *filename,unsigned lineno)
{
	char* _assertstring = "Assertion failed: %s, file %s, line %d";
	char assertbuf[1024];

	HANDLE hErr ;
	DWORD written;

	if(sprintf_s(assertbuf,1024, _assertstring,expr,filename,lineno) >= 0)
	{
		hErr = GetStdHandle(STD_ERROR_HANDLE);
		if(hErr!=INVALID_HANDLE_VALUE && hErr!=NULL)
		{
			if(GetFileType(hErr) == FILE_TYPE_CHAR)
				WriteConsole(hErr, assertbuf, (unsigned long)strlen(assertbuf), &written, NULL);
		}
		int nCode;
		nCode = ::MessageBox(0,assertbuf,"Warning",	MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
	}
}

#include <time.h>

FILE* LogFile()
{
	static FILE* file=0;
	if(file==0) {
		file=fopen("log.txt","ab");
		int ic=0;
		while(file==0) {
			char fbuf[256];
			sprintf_s(fbuf,256,"log[%d].txt",ic++);
			file=fopen(fbuf,"ab");
		}

		time_t t; 
		t=time(NULL); 
		struct tm *ptr; 
		ptr=localtime(&t); 
		fprintf(file,"--------------\n%s------------------\n",asctime(ptr)); 
	}
	fflush(file);
	return file;
}


int ArgPos(char *str, int argc, char **argv) {
	int a;
	for (a = 1; a < argc; a++) if (!strcmp(str, argv[a])) {
		if (a == argc - 1) {
			printf("Argument missing for %s\n", str);
			exit(1);
		}
		return a;
	}
	return -1;
}


namespace EXP_WORKSPACE {
	const int exp_100table_num = 100000;
	static double exp_100table[exp_100table_num];
	static double exp_nby[6];
	static bool exp_100table_inited = false;
	const int one_per_dim = exp_100table_num/100;
	const double exp_100table_dv = 100.0/exp_100table_num;
	void init_exp_100table()
	{
		for (int i=0;i<exp_100table_num;i++)
		{
			exp_100table[i] = exp(-100.0*i/(double)exp_100table_num);
		}
		exp_100table_inited = true;
		exp_nby[0]=1;
		exp_nby[1]=1;
		exp_nby[2]=2*1;
		exp_nby[3]=3*2*1;
		exp_nby[4]=4*3*2*1;
		exp_nby[5]=5*4*3*2*1;
	}
}

double fast_exp(double v) 
{
	if(v>0) v=0;
	if(v<-100) v = -100;
	if(!EXP_WORKSPACE::exp_100table_inited) EXP_WORKSPACE::init_exp_100table();
	int id = -v*1000;
	double dx = v + id*EXP_WORKSPACE::exp_100table_dv;
	return EXP_WORKSPACE::exp_100table[id] * (1 + dx + dx*dx/2);
}
